package com.chefu.evaluation.service.impl;

import com.chefu.common.exception.CfException;
import com.chefu.common.exception.ExceptionEnum;
import com.chefu.common.pojo.PageResult;
import com.chefu.common.utils.BeanHelper;
import com.chefu.evaluation.dto.SOContentDTO;
import com.chefu.evaluation.dto.SOProContentDTO;
import com.chefu.evaluation.pojo.ServiceOrderEval;
import com.chefu.evaluation.pojo.ServiceProviderInfo;
import com.chefu.evaluation.service.ServOrderEvalService;
import com.chefu.evaluation.vo.ContentVO;
import com.chefu.evaluation.vo.SOProSearchVO;
import com.chefu.evaluation.vo.SOSearchVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

@Service
public class ServOrderEvalServiceImpl implements ServOrderEvalService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public PageResult<ServiceOrderEval> findByPage(Integer pageNum, Integer pageSize, SOSearchVO soSearchVO) {
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(pageNum - 1, pageSize, sort);
        Query query = new Query();
        if (StringUtils.isNotEmpty(soSearchVO.getOrderId())) {
            Pattern pattern = Pattern.compile("^.*"+ soSearchVO.getOrderId() +".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("orderId").regex(pattern));
        }
        if (StringUtils.isNotEmpty(soSearchVO.getCarOwner())) {
            query.addCriteria(Criteria.where("carOwnerName").regex(".*?\\" + soSearchVO.getCarOwner() + ".*"));
        }
        if (StringUtils.isNotEmpty(soSearchVO.getServiceStatus())) {
            query.addCriteria(Criteria.where("serviceStatus").is(soSearchVO.getServiceStatus()));
        }
        if (StringUtils.isNotEmpty(soSearchVO.getServiceProvider())) {
            query.addCriteria(Criteria.where("providerName").regex(".*?\\" + soSearchVO.getServiceProvider() + ".*"));
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        if (StringUtils.isNotEmpty(soSearchVO.getStartTime()) && StringUtils.isEmpty(soSearchVO.getEndTime())) {
            try {
                Date startTime = simpleDateFormat.parse(soSearchVO.getStartTime());
                query.addCriteria(Criteria.where("createTime").gte(startTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        if (StringUtils.isNotEmpty(soSearchVO.getEndTime()) && StringUtils.isEmpty(soSearchVO.getStartTime())) {
            try {
                Date endTime = simpleDateFormat.parse(soSearchVO.getEndTime());
                endTime = nextDay(endTime);
                query.addCriteria(Criteria.where("createTime").lt(endTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        if (StringUtils.isNotEmpty(soSearchVO.getStartTime()) && StringUtils.isNotEmpty(soSearchVO.getEndTime())) {
            try {
                Date startTime = simpleDateFormat.parse(soSearchVO.getStartTime());
                Date endTime = simpleDateFormat.parse(soSearchVO.getEndTime());
                endTime = nextDay(endTime);
                query.addCriteria(Criteria.where("createTime").gte(startTime).lt(endTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        //总条数
        Long total = mongoTemplate.count(query, ServiceOrderEval.class);
        //查询记录
        List<ServiceOrderEval> serviceOrderEvals = mongoTemplate.find(query.with(pageable), ServiceOrderEval.class);
        Long totalPage = (total - 1) / pageSize + 1;
        return new PageResult<ServiceOrderEval>(total, totalPage, serviceOrderEvals);
    }

    @Override
    public void saveEvaluation(String orderId, ContentVO contentVO) {
        //todo 调用服务订单的接口查询订单相关内容
        try {
            ServiceOrderEval serviceOrderEval = new ServiceOrderEval();
            serviceOrderEval.setOrderId(orderId);
            //根据orderId查询服务信息
            serviceOrderEval.setProviderId("1376965509077127168");
            serviceOrderEval.setProviderName("小拇指上地店");
            //获取订单时间
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date orderTime = simpleDateFormat.parse("2021-02-25 18:65:45");
            serviceOrderEval.setOrderTime(orderTime);

            serviceOrderEval.setCreateTime(new Date());

            //从token中获取车主信息
            serviceOrderEval.setCarOwnerId("1376949206748610560");
            serviceOrderEval.setCarOwnerName("大狐狸");

            //获取提交的评价信息
            serviceOrderEval.setScores(contentVO.getScores());
            Double[] scores = contentVO.getScores();
            Integer contentScore = ((int) (scores[0] + scores[1] + scores[2]) * 2) / 3;
            serviceOrderEval.setScore(contentScore / 2.0);
            serviceOrderEval.setContent(contentVO.getContent());
            String[] evalImages = contentVO.getImages().split(",");
            serviceOrderEval.setImages(evalImages);

            //从订单id获取配件id
            serviceOrderEval.setServiceItem("洗车，换机油");
            //从订单获取信息 tb_auto_parts_order表的actual_fee
            serviceOrderEval.setTotalFee(445.6);
            serviceOrderEval.setState("0");
            mongoTemplate.save(serviceOrderEval);

            //更新服务商的平均评分
            ServiceProviderInfo serviceProviderInfo = mongoTemplate.findOne(
                    new Query().addCriteria(Criteria.where("providerId").is("1376965509077127168")), ServiceProviderInfo.class);
            Integer score = (int) (serviceProviderInfo.getScore() * 2);
            Integer contentNum = Integer.parseInt(serviceProviderInfo.getContentNum());
            Double newScore = (score * contentNum + contentScore) / (contentNum + 1) / 2.0;
            Query query = new Query(Criteria.where("providerId").is("1376965509077127168"));
            Update update = new Update();
            update.set("score", newScore);
            update.set("contentNum", String.valueOf(contentNum + 1));
            mongoTemplate.updateMulti(query, update, ServiceProviderInfo.class);
        } catch (ParseException e) {
            e.printStackTrace();
            throw new CfException(ExceptionEnum. INSERT_OPERATION_FAIL);
        }
    }

    @Override
    public PageResult<SOContentDTO> findByCarOwner(Integer pageNum, Integer pageSize) {
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(pageNum - 1, pageSize, sort);
        Query query = new Query();
        //todo 从token中获取车主的信息 暂时写死
        query.addCriteria(Criteria.where("carOwnerId").is("1376949206748610560"));
        //总条数
        Long total = mongoTemplate.count(query, ServiceOrderEval.class);
        //查询记录
        List<ServiceOrderEval> serviceOrderEvals = mongoTemplate.find(query.with(pageable), ServiceOrderEval.class);
        List<SOContentDTO> soContentDTOS = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (ServiceOrderEval serviceOrderEval : serviceOrderEvals) {
            SOContentDTO soContentDTO = BeanHelper.copyProperties(serviceOrderEval, SOContentDTO.class);
            Date createTime = serviceOrderEval.getCreateTime();
            soContentDTO.setTime(sdf.format(createTime));
            String providerId = serviceOrderEval.getProviderId();
            ServiceProviderInfo providerInfo = mongoTemplate.findOne(
                    new Query().addCriteria(Criteria.where("providerId").is(providerId)), ServiceProviderInfo.class);
            soContentDTO.setServProInfo(providerInfo);
            soContentDTOS.add(soContentDTO);
        }
        Long totalPage = (total - 1) / pageSize + 1;
        return new PageResult<SOContentDTO>(total, totalPage, soContentDTOS);
    }

    @Override
    public PageResult<SOProContentDTO> findByPartsProvider(Integer pageNum, Integer pageSize, SOProSearchVO soProSearchVO) {
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(pageNum - 1, pageSize, sort);
        Query query = new Query();
        //todo 根据token获取用户id，查询用户所在的服务商id
        query.addCriteria(Criteria.where("providerId").is("1376965509077127168"));

        if (StringUtils.isNotEmpty(soProSearchVO.getOrderId())) {
            Pattern pattern = Pattern.compile("^.*"+ soProSearchVO.getOrderId() +".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("orderId").regex(pattern));
        }
        if (StringUtils.isNotEmpty(soProSearchVO.getCarOwner())) {
            query.addCriteria(Criteria.where("carOwnerName").regex(".*?\\" + soProSearchVO.getCarOwner() + ".*"));
        }
        if (soProSearchVO.getScore() != null) {
            query.addCriteria(Criteria.where("score").is(soProSearchVO.getScore()));
        }
        if (StringUtils.isNotEmpty(soProSearchVO.getServiceItem())) {
            query.addCriteria(Criteria.where("serviceItem").regex(".*?\\" + soProSearchVO.getServiceItem() + ".*"));
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        if (StringUtils.isNotEmpty(soProSearchVO.getStartTime()) && StringUtils.isEmpty(soProSearchVO.getEndTime())) {
            try {
                Date startTime = simpleDateFormat.parse(soProSearchVO.getStartTime());
                query.addCriteria(Criteria.where("createTime").gte(startTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        if (StringUtils.isNotEmpty(soProSearchVO.getEndTime()) && StringUtils.isEmpty(soProSearchVO.getStartTime())) {
            try {
                Date endTime = simpleDateFormat.parse(soProSearchVO.getEndTime());
                endTime = nextDay(endTime);
                query.addCriteria(Criteria.where("createTime").lt(endTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        if (StringUtils.isNotEmpty(soProSearchVO.getStartTime()) && StringUtils.isNotEmpty(soProSearchVO.getEndTime())) {
            try {
                Date startTime = simpleDateFormat.parse(soProSearchVO.getStartTime());
                Date endTime = simpleDateFormat.parse(soProSearchVO.getEndTime());
                endTime = nextDay(endTime);
                query.addCriteria(Criteria.where("createTime").gte(startTime).lt(endTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        //总条数
        Long total = mongoTemplate.count(query, ServiceOrderEval.class);
        //查询记录
        List<ServiceOrderEval> serviceOrderEvals = mongoTemplate.find(query.with(pageable), ServiceOrderEval.class);
        List<SOProContentDTO> soProContentDTOS = BeanHelper.copyWithCollection(serviceOrderEvals, SOProContentDTO.class);
        Long totalPage = (total - 1) / pageSize + 1;
        return new PageResult<SOProContentDTO>(total, totalPage, soProContentDTOS);
    }

    @Override
    public void deleteEvaluation(String id) {
        ServiceOrderEval orderEval = mongoTemplate.findOne(new Query().addCriteria(Criteria.where("id").is(id)), ServiceOrderEval.class);
        if (orderEval == null) {
            throw new CfException(ExceptionEnum.DELETE_OPERATION_FAIL);
        }
        //todo  根据token获取用户信息，判断用户是否具备运营角色
        if (true) {
            mongoTemplate.remove(new Query().addCriteria(Criteria.where("id").is(id)), ServiceOrderEval.class);
        } else {
            throw new CfException(ExceptionEnum.DELETE_OPERATION_FAIL);
        }
    }

    private Date nextDay(Date date){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, 1);
        return calendar.getTime();
    }
}
